package com.autonavi.yunda.yunji.service;

import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.core.model.dto.ProjectDTO;
import com.autonavi.yunda.yunji.core.model.dto.UserProjectRelationDTO;
import com.autonavi.yunda.yunji.core.model.mappers.UserProjectRelationMapper;
import com.autonavi.yunda.yunji.core.service.ProjectService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cizhong.wcs
 * @date 2023/9/4 14:38
 */
@Slf4j
@Component
public class UserProjectService {
    @Resource
    private UserProjectRelationMapper userProjectRelationMapper;
    @Resource
    private ProjectService projectService;
    @Resource
    private UserProjectService userProjectService;
    @Resource
    private FactoryUserService factoryUserService;


    public List<String> listUserProjectIds(String userId) {
        Long bdId = factoryUserService.getCurrentUserBdId();
        List<String> projectIds = projectService.listAll(bdId)
                .stream().map(ProjectDTO::getProjectId)
                .collect(Collectors.toList());
        if (projectIds.isEmpty()) {
            return new ArrayList<>();
        }
        return userProjectRelationMapper
                .selectList(
                        new QueryWrapper<UserProjectRelationDTO>()
                                .eq("user_id", userId)
                                .in("project_id", projectIds)
                )
                .stream().map(UserProjectRelationDTO::getProjectId).collect(Collectors.toList());
    }

    public Map<String, List<String>> fetchUserProjectIdsMap(List<String> userIds, Long bdId) {
        if (userIds.isEmpty()) {
            return new HashMap<>(8);
        }
        Set<String> projectIds = projectService.listAll(bdId)
                .stream().map(ProjectDTO::getProjectId)
                .collect(Collectors.toSet());
        return userProjectRelationMapper
                .selectList(new QueryWrapper<UserProjectRelationDTO>().in("user_id", userIds))
                .stream()
                .collect(
                        Collectors.groupingBy(
                                UserProjectRelationDTO::getUserId,
                                Collectors.filtering(p -> projectIds.contains(p.getProjectId()),
                                        Collectors.mapping(UserProjectRelationDTO::getProjectId, Collectors.toList()))

                        )
                );
    }

    public void addUserProjectId(String userId, String projectId, String operator) {
        List<String> existsProjectIds = listUserProjectIds(userId);
        existsProjectIds.add(projectId);
        List<String> updateProjectIds = existsProjectIds.stream().distinct().collect(Collectors.toList());
        userProjectService.updateUserProjectIds(userId, updateProjectIds, operator);
    }

    /**
     * todo 根据新的权限进行调整
     *
     * @param userId
     * @param projectIds
     * @param operator
     */
    @Transactional
    public void updateUserProjectIds(String userId, List<String> projectIds, String operator) {
        Long bdId = factoryUserService.getCurrentUserBdId();
        AmapPreconditions.checkNotBlank(userId);
        AmapPreconditions.checkNotNull(projectIds);
        List<String> updateProjectIds = projectService.findByProjectIds(projectIds)
                .stream()
                .filter(dto -> bdId == null || dto.getBdId().equals(bdId))
                .map(ProjectDTO::getProjectId)
                .collect(Collectors.toList());
        List<String> existsProjectIds = listUserProjectIds(userId);
        List<String> deleteProjectIds = existsProjectIds.stream().filter(f -> !updateProjectIds.contains(f)).collect(Collectors.toList());
        deleteUserProjectIds(userId, deleteProjectIds);
        log.info("userId:{},deleteProjectIds:{}", userId, deleteProjectIds);
        List<String> addProjectIds = new ArrayList<>(updateProjectIds);
        addProjectIds.removeAll(existsProjectIds);
        if (!CollectionUtils.isEmpty(addProjectIds)) {
            log.info("userId:{},addProjectIds:{}", userId, addProjectIds);
            List<UserProjectRelationDTO> addDTOList = addProjectIds.stream()
                    .map(projectId -> new UserProjectRelationDTO(userId, projectId, operator))
                    .collect(Collectors.toList());
            userProjectRelationMapper.insertBatchSomeColumn(addDTOList);
        }
    }


    public void deleteUserProjectIds(String userId, List<String> projectIds) {
        AmapPreconditions.checkNotBlank(userId);
        if (projectIds.isEmpty()) {
            return;
        }
        userProjectRelationMapper.delete(
                new QueryWrapper<UserProjectRelationDTO>()
                        .eq("user_id", userId)
                        .in("project_id", projectIds)
        );
    }
}
